package easy.trace.agent.support;


import easy.trace.Span;
import easy.trace.agent.SyncTransfer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DefaultSyncTransfer implements SyncTransfer {
    private static Logger logger = LoggerFactory.getLogger(easy.trace.agent.support.DefaultSyncTransfer.class);
    private ArrayBlockingQueue<Span> queue;
    private ScheduledExecutorService executors = null;
    private List<Span> spansCache;
    private volatile boolean isReady;
    private ConcurrentHashMap<String, Boolean> isServiceReady = new ConcurrentHashMap();
    private ConcurrentHashMap<String, Integer> serviceInfo = new ConcurrentHashMap();
    private GenerateTraceId generateTraceId = new GenerateTraceId(0L);
    private TraceService traceService;
    private Long flushSize;
    private Long waitTime;
    private easy.trace.agent.support.DefaultSyncTransfer.TransferTask task;
    private String appName;


    @Override
    public void setTraceService(TraceService traceService) {
        this.traceService = traceService;
    }

    public DefaultSyncTransfer(TraceConfiguration c) {
        this.flushSize = c.getFlushSize() == null ? 1024L : c.getFlushSize().longValue();
        this.waitTime = c.getDelayTime() == null ? 60000L : c.getDelayTime().longValue();
        this.queue = new ArrayBlockingQueue(c.getQueueSize().intValue());
        this.spansCache = new ArrayList();
        this.executors = Executors.newSingleThreadScheduledExecutor();
        this.task = new easy.trace.agent.support.DefaultSyncTransfer.TransferTask();
        this.appName = c.getApplicationName();
    }

    @Override
    public String appName() {
        return this.appName;
    }

    @Override
    public boolean isReady() {
        return this.isReady;
    }

    @Override
    public boolean isServiceReady(String serviceName) {
        return serviceName != null && this.isServiceReady.containsKey(serviceName) ? ((Boolean)this.isServiceReady.get(serviceName)).booleanValue() : false;
    }

    @Override
    public void syncSend(Span span) {
        try {
            if (this.isReady()) {
                this.queue.add(span);
            }
        } catch (Exception var3) {
            logger.info(" span : ignore ..");
        }

    }

    @Override
    public void start() throws Exception {
        if (this.traceService != null && !this.task.isAlive()) {
            this.task.start();
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    easy.trace.agent.support.DefaultSyncTransfer.this.cancel();
                }
            });
        } else if (this.traceService == null) {
            throw new Exception("TraceServie is null.can't starting SyncTransfer");
        }

    }

    @Override
    public void cancel() {
        this.task.interrupt();
    }

    @Override
    public String getServiceId(String name, Integer type) {
        String serviceId = null;
        serviceId = this.traceService.getServiceId(name, type);
        logger.debug("!!!!!!" + name + "!~" + type);
        if (null == serviceId) {
            this.isServiceReady.putIfAbsent(name, false);
            this.serviceInfo.put(name, type);
        }

        return serviceId;
    }

    @Override
    public Long getTraceId() {
        return this.generateTraceId.getTraceId();
    }

    @Override
    public Long getSpanId() {
        return this.generateTraceId.getTraceId();
    }

    private class TransferTask extends Thread {
        TransferTask() {
            this.setName("TransferTask-Thread");
        }

        @Override
        public void run() {
            while(true) {
                try {
                    if (!easy.trace.agent.support.DefaultSyncTransfer.this.isReady()) {
                        easy.trace.agent.support.DefaultSyncTransfer.logger.info("----------is not ready");
                        boolean r = easy.trace.agent.support.DefaultSyncTransfer.this.traceService.registerService(easy.trace.agent.support.DefaultSyncTransfer.this.appName(), new ArrayList());
                        if (r) {
                            easy.trace.agent.support.DefaultSyncTransfer.this.generateTraceId = new GenerateTraceId(easy.trace.agent.support.DefaultSyncTransfer.this.traceService.getSeed());
                            easy.trace.agent.support.DefaultSyncTransfer.this.isReady = true;
                        } else {
                            synchronized(this) {
                                this.wait(easy.trace.agent.support.DefaultSyncTransfer.this.waitTime.longValue());
                            }
                        }
                    } else {
                        easy.trace.agent.support.DefaultSyncTransfer.logger.info("----------is ready");

                        while(!easy.trace.agent.support.DefaultSyncTransfer.this.task.isInterrupted()) {
                            Iterator var7 = easy.trace.agent.support.DefaultSyncTransfer.this.isServiceReady.entrySet().iterator();

                            while(var7.hasNext()) {
                                Entry<String, Boolean> entry = (Entry)var7.next();
                                if (!((Boolean)entry.getValue()).booleanValue()) {
                                    Integer type = (Integer) easy.trace.agent.support.DefaultSyncTransfer.this.serviceInfo.get(entry.getKey());
                                    easy.trace.agent.support.DefaultSyncTransfer.logger.debug("%%%%%%%%%%%%%" + (String)entry.getKey() + "%%%%" + type);
                                    boolean rx = easy.trace.agent.support.DefaultSyncTransfer.this.traceService.registerService(easy.trace.agent.support.DefaultSyncTransfer.this.appName(), (String)entry.getKey(), type);
                                    if (rx) {
                                        entry.setValue(true);
                                    }
                                }
                            }

                            Span first = (Span) easy.trace.agent.support.DefaultSyncTransfer.this.queue.take();
                            easy.trace.agent.support.DefaultSyncTransfer.this.spansCache.add(first);
                            easy.trace.agent.support.DefaultSyncTransfer.this.queue.drainTo(easy.trace.agent.support.DefaultSyncTransfer.this.spansCache);
                            easy.trace.agent.support.DefaultSyncTransfer.this.traceService.sendSpan(easy.trace.agent.support.DefaultSyncTransfer.this.spansCache);
                            easy.trace.agent.support.DefaultSyncTransfer.this.spansCache.clear();
                            easy.trace.agent.support.DefaultSyncTransfer.logger.debug("****easy.trace send span*****");
                        }
                    }
                } catch (Throwable var6) {
                    var6.printStackTrace();
                    easy.trace.agent.support.DefaultSyncTransfer.logger.info(var6.getMessage());
                }
            }
        }
    }
}

